package services

import (
	"crypto/rand"
	"encoding/hex"
	"log"
	"sync"
	"time"
)

// Token结构体，包含过期时间和相关信息
type TokenInfo struct {
	CarID       string    // 关联的carID
	ChannelType string    // 频道类型
	UserID      string    // 用户ID，可选
	CreatedAt   time.Time // 创建时间
	ExpiresAt   time.Time // 过期时间
}

// Token存储和管理
type TokenService struct {
	tokens map[string]TokenInfo // token -> TokenInfo
	mutex  sync.RWMutex
	// 定期清理过期token的计时器
	cleanupTicker *time.Ticker
}

// 单例实例
var (
	tokenService     *TokenService
	tokenServiceOnce sync.Once
)

// 获取TokenService单例
func GetTokenService() *TokenService {
	tokenServiceOnce.Do(func() {
		tokenService = &TokenService{
			tokens:        make(map[string]TokenInfo),
			cleanupTicker: time.NewTicker(10 * time.Minute),
		}
		// 启动后台清理任务
		go tokenService.cleanupExpiredTokens()
	})
	return tokenService
}

// 生成随机Token
func GenerateToken(length int) (string, error) {
	bytes := make([]byte, length/2)
	if _, err := rand.Read(bytes); err != nil {
		return "", err
	}
	return hex.EncodeToString(bytes), nil
}

// 创建新的Token
func (ts *TokenService) CreateToken(carID, channelType, userID string, ttl time.Duration) (string, error) {
	// 生成32字节的随机token
	token, err := GenerateToken(32)
	if err != nil {
		return "", err
	}

	now := time.Now()
	tokenInfo := TokenInfo{
		CarID:       carID,
		ChannelType: channelType,
		UserID:      userID,
		CreatedAt:   now,
		ExpiresAt:   now.Add(ttl),
	}

	// 存储token
	ts.mutex.Lock()
	ts.tokens[token] = tokenInfo
	ts.mutex.Unlock()

	log.Printf("Created token for carID: %s, channel: %s, expires in: %v",
		carID, channelType, ttl)
	return token, nil
}

// 验证Token
func (ts *TokenService) ValidateToken(token string) (bool, TokenInfo) {
	ts.mutex.RLock()
	defer ts.mutex.RUnlock()

	info, exists := ts.tokens[token]
	if !exists {
		return false, TokenInfo{}
	}

	// 检查是否过期
	if time.Now().After(info.ExpiresAt) {
		return false, TokenInfo{}
	}

	return true, info
}

// 移除Token（例如在使用后）
func (ts *TokenService) RemoveToken(token string) {
	ts.mutex.Lock()
	defer ts.mutex.Unlock()
	delete(ts.tokens, token)
}

// 清理过期的tokens
func (ts *TokenService) cleanupExpiredTokens() {
	for range ts.cleanupTicker.C {
		now := time.Now()
		ts.mutex.Lock()
		for token, info := range ts.tokens {
			if now.After(info.ExpiresAt) {
				delete(ts.tokens, token)
			}
		}
		ts.mutex.Unlock()
		log.Println("Cleaned up expired tokens")
	}
}

// 关闭服务
func (ts *TokenService) Shutdown() {
	ts.cleanupTicker.Stop()
}
